package cz.proks.bank.manager;

import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cz.proks.bank.client.ScoreServiceClient;
import cz.proks.bank.dao.LoanDao;
import cz.proks.bank.domain.Account;
import cz.proks.bank.domain.Loan;
import cz.proks.bank.domain.OperationLog.OperationType;
import cz.proks.bank.manager.exeception.AccountNotFoundException;
import cz.proks.bank.manager.exeception.LoanException;
import cz.proks.bank.manager.exeception.LoanRejectedException;
import cz.proks.bank.manager.exeception.UnsupportedCurrencyException;
import cz.proks.bank.service.scoreservice.Score;
import cz.proks.bank.service.scoreservice.ScoreRequest;

@Service
public class LoanManager {
	private static final double CRITERIA = 0.6;
	
	@Autowired
	private LoanDao loanDao;
	
	@Autowired
	private ScoreServiceClient scoreClient;
	
	@Autowired
	private AccountManager accountManager;
	
	@Autowired
	private CurrencyManager currencyManager;
	
	@Autowired
	private OperationLogManager logManager;
	
	public Loan createLoan(int accountNumber, long amount, String currency) throws LoanRejectedException {
		try {
			Account account = accountManager.getAccount(accountNumber);
			ScoreRequest request = toScoreRequest(account, amount, currency);
			
			Score score = scoreClient.getClientBonity(request);
			double bonity = score.getBonity();
			
			if (bonity > CRITERIA)
				throw new LoanRejectedException("Client has bad bonity " + bonity);
			
			Loan loan = new Loan();
			
			loan.setAccount(account);
			loan.setCurrency(currency);
			loan.setOriginalAmount(amount);
			loan.setRemainingAmount(amount);
			loan.setLoanDate(new Date());
			
			loanDao.create(loan);
			
			logManager.createLog(account, account.getBank(), OperationType.NEW_LOAN, new Date(), "Created new loan. Lent " + amount + " " + currency);
			return loan;
			
		} catch (UnsupportedCurrencyException e) {
			throw new LoanRejectedException(e);
		} catch (AccountNotFoundException e) {
			throw new LoanRejectedException(e);
		}
	}
	
	public Loan getLoan(long loanId) {
		Loan loan = loanDao.get(loanId);
		
		return loan;
	}
	
	public Loan insertRepayment(long loanId, long amount, String currency) throws LoanException {
		try {
			Loan loan = getLoan(loanId);
			Account account = loan.getAccount();
			
			if (loan == null)
				throw new LoanException("No loan!");
			
			long ammountToRepay = currencyManager.convert(amount, currency, loan.getCurrency());
			
			if (ammountToRepay < 0)
				throw new LoanException("Cannot repay less than 0!");
			
			loan.setRemainingAmount(loan.getRemainingAmount() - ammountToRepay < 0 ? 0 : loan.getRemainingAmount() - ammountToRepay);
			
			loanDao.update(loan);
			
			logManager.createLog(account, account.getBank(), OperationType.LOAN_REPAYMENT, new Date(), "Paid " + amount + " " + currency + " to loan + " + loan.getId() + ". Ramainig " + loan.getRemainingAmount() + " " + loan.getCurrency());
			
			return loan;
		} catch (UnsupportedCurrencyException e) {
			throw new LoanException("Currency " + currency + "is not supported!");
		}			
	}
	
	private ScoreRequest toScoreRequest(Account account, long amount, String currency) throws LoanRejectedException, UnsupportedCurrencyException {
		if (account == null)
			throw new LoanRejectedException("No account!");
		
		ScoreRequest request = new ScoreRequest();
		
		long requestedAmount = currencyManager.convert(amount, currency, account.getCurrency());
		
		request.setAvailableMoney(account.getAvailableMoney());
				
		request.setRequestedLoan(requestedAmount);
		
		request.setTotalLoans(getTotalLoans(account));
		
		return request;
		
	}
	
	private long getTotalLoans(Account account) {
		long totalLoans = 0;
		
		if (account == null || account.getLoans() == null)			
			return totalLoans;
				
		for (Loan loan : account.getLoans()) {
			totalLoans += loan.getRemainingAmount();
		}
		
		return totalLoans;
	}
}
